#ifndef EXT_TYPE_TRAITS

#include<type_traits>
#define PURE_TYPE(A) typename std::remove_reference<typename std::remove_cv<decltype(A)>::type>::type

#define ADD_LEFT(T) typename std::add_lvalue_reference<T>::type
#define ADD_RIGHT(T) typename std::add_rvalue_reference<T>::type
#define ADD_CONST(T) typename std::add_const<T>::type

#define LEFT_TYPE(A) ADD_LEFT(PURE_TYPE(A))
#define RIGHT_TYPE(A) ADD_RIGHT(PURE_TYPE(A))
#define CONST_TYPE(A) ADD_CONST(PURE_TYPE(A))
#define CONST_LEFT_TYPE(A) ADD_LEFT(CONST_TYPE(A))
#define CONST_RIGHT_TYPE(A) ADD_RIGHT(CONST_TYPE(A))

#define LEFT_FORWARD(A) std::forward<LEFT_TYPE(A)>(A)
#define RIGHT_FORWARD(A) std::forward<RIGHT_TYPE(A)>(A)
#define CONST_FORWARD(A) std::forward<CONST_TYPE(A)>(A)
#define CONST_LEFT_FORWARD(A) std::forward<CONST_LEFT_TYPE(A)>(A)
#define CONST_RIGHT_FORWARD(A) std::forward<CONST_RIGHT_TYPE(A)>(A)

#define EXT_TYPE_TRAITS
#endif